home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Program: PopUpMenu Demo for System 7.0
- ** File: PopUpMenu.c
- ** Written By: Joe Zobkiw
- ** Date: Saturday, June 1, 1991 • 11:32:11 AM
- **
- ** Copyright © 1991 Joe Zobkiw
- ** All rights reserved.
- **
- ** AFL Zobkiw @ America Online
- */
-
- /* ----------------------------------------------
- This is a short example (and a very simple one as well) of how to use the
- standard Sytem 7.0 Pop-Up Menu control. This is not the only way to use the
- control, it can be done any number of ways.
-
- I for instance, choose to implement a statText item to be the "title" of my
- control. You can also give the control a title of it’s own and have it draw
- it for you automatically.
-
- Some other cool things are:
-
- • DrawGrayFrameMinusText() routine which handles drawing the “sample”
- area outline in the dialog.
- • ZoomRect() which allows you to draw “Finder like” zoom rectangles.
- • DialogFilter() which shows you a simple way to handle a dialog filter.
-
- Take this code for what it is worth…just a quick hack to learn how to do it
- simply and easily. Have fun and feel free to use this code if you like. This
- code is hereby in the pubic domain. (It said public, I changed it ;)
-
- There are not many comments since this stuff is pretty darned easy!
- ---------------------------------------------- */
-
- #include "PopUpMenu.h"
- #include <string.h>
- #include <Sound.h>
-
-
- /* --- global variables ------------------------- */
-
- DialogPtr gDialog = nil;
- ControlHandle gFontPopUp = nil;
- ControlHandle gAlignPopUp = nil;
- ControlHandle gSizePopUp = nil;
- Rect gFontLabelRect;
- Rect gAlignLabelRect;
- Rect gSizeLabelRect;
- Rect gSampleRect;
- StringHandle gSampleStr = nil;
- short gAlign = ALIGN_LEFT_ITEM;
- short gFontNum = 0;
- short gSize = 9;
- short gBrothersHead = 0;
-
- #define SysFontFamPtr ((short *) 0x0BA6)
- #define SysFontSizePtr ((short *) 0x0BA8)
- #define CurFMInputPtr ((long *) 0x0988)
- #define LastSpExtraPtr ((long *) 0x0B4C)
-
- static void ChangeSystemFont(short fontNum, short fontSize)
- {
- if ((*SysFontFamPtr != fontNum) || (*SysFontSizePtr != fontSize)) {
- *SysFontFamPtr = fontNum;
- *SysFontSizePtr = fontSize;
- *CurFMInputPtr = -1L;
- *LastSpExtraPtr = -1L; /* tells Font Manager to flush & reload font cache */
- } /* otherwise, *SysFontFamPtr == fontNum && *SysFontSizePtr == fontSize, do
- nothing */
- } /* ChangeSystemFont */
-
-
- /* ----------------------------------------------
- This is our main() program.
- ---------------------------------------------- */
- main() {
- InitToolBox();
- CheckEnvironment();
-
- CreateObjects();
-
- ZoomFromCorner(gDialog);
-
- DoDialog();
-
- ExitApplication(FALSE);
- }
-
- /* ----------------------------------------------
- Center a rectangle in the screen…not the exact
- algorithm that System 7 uses…
- but good enough for our zoomrect routine.
- ---------------------------------------------- */
- #define Max(x, y) ((x) > (y) ? (x) : (y))
-
- Rect CenterRect(Rect r)
- {
- short left, top;
-
- left = (screenBits.bounds.right - (r.right - r.left)) / 2;
- top = (screenBits.bounds.bottom - (r.bottom - r.top)) / 3;
- top = Max(top, GetMBarHeight() + 1);
-
- r.right += left - r.left;
- r.left = left;
- r.bottom += top - r.top;
- r.top = top;
-
- /* this is needed to appease the rects to look better under system 7.0 */
- r.top += 35;
- r.bottom += 90;
-
- return(r);
- }
-
- /* ----------------------------------------------
- Zoom our dialog window from the corner of the
- screen…ala Welch.
- ---------------------------------------------- */
- void ZoomFromCorner(DialogPtr dialog)
- {
- Rect smallRect = {0,0,1,1};
- Rect middleRect;
- Rect dialogRect;
-
- dialogRect = dialog->portRect;
- dialogRect = CenterRect(dialogRect);
- middleRect = dialogRect;
- InsetRect(&middleRect,100,100);
-
- DrawMenuBar(); /* this is the secret ingredient */
-
- ZoomRect(&smallRect, &middleRect, TRUE, TRUE);
- ZoomRect(&middleRect, &dialogRect, TRUE, TRUE);
- }
-
- /* ----------------------------------------------
- Zoom our dialog window from the corner of the
- screen…ala Welch.
- ---------------------------------------------- */
- void ZoomToCorner(DialogPtr dialog)
- {
- Rect smallRect = {0,0,1,1};
- Rect middleRect;
- Rect dialogRect;
-
- dialogRect = dialog->portRect;
- dialogRect = CenterRect(dialogRect);
- middleRect = dialogRect;
- InsetRect(&middleRect,100,100);
-
- DrawMenuBar(); /* this is the secret ingredient */
-
- ZoomRect(&middleRect, &dialogRect, FALSE, TRUE);
- ZoomRect(&smallRect, &middleRect, FALSE, TRUE);
- }
-
- /* ----------------------------------------------
- Handle our dialog here…this is the meat of the
- program.
- ---------------------------------------------- */
- void DoDialog(void)
- {
- GrafPtr savePort;
- Boolean dialogDone = FALSE;
- short itemHit, part, item, fontNum;
- Point pt;
- Rect r, r2;
- MenuHandle menuHandle = nil;
- popupPrivateDataHdl privateData = nil;
- Str255 fontName, sizeStr;
- long sizeLong;
-
- GetPort(&savePort);
- SetPort(gDialog);
-
- ShowWindow(gDialog);
-
- /* draw initial font properly */
- item = GetCtlValue(gFontPopUp);
- privateData = (MenuHandle)(*gFontPopUp)->contrlData;
- menuHandle = (popupPrivateDataHdl)(*privateData)->mHandle;
- GetItem(menuHandle, item, &fontName);
- GetFNum(fontName, &fontNum);
- if (fontNum != gFontNum) {
- gFontNum = fontNum;
- DrawSampleString();
- }
-
- while (!dialogDone) {
- ModalDialog((ProcPtr)&DialogFilter,&itemHit);
- switch(itemHit)
- {
- case QUIT_ITEM:
- HideWindow(gDialog);
- dialogDone = TRUE;
- ZoomToCorner(gDialog);
- break;
-
- case ICON_ITEM: {
- long lMnuAndItm;
- Point pt;
-
- GetMouse(&pt);
- LocalToGlobal(&pt);
- privateData = (MenuHandle)(*gSizePopUp)->contrlData;
- menuHandle = (popupPrivateDataHdl)(*privateData)->mHandle;
-
- /* save old values of low-memory globals: */
- {
- short saveSysFontFam = *SysFontFamPtr;
- short saveSysFontSize = *SysFontSizePtr;
-
- /* set the font information from instance variables: */
- ChangeSystemFont(geneva, 9);
-
- lMnuAndItm = PopUpMenuSelect(menuHandle, pt.v, pt.h, 0);
-
- /* set the font information back to saved variables: */
- ChangeSystemFont(saveSysFontFam, saveSysFontSize);
- }
-
- break;
- }
-
-
- /****************
- PlaySound(AHEM_SND_ID);
- gBrothersHead++;
- if (gBrothersHead == 9) {
- Alert(BROTHERS_HEAD_ALRT_ID,nil);
- gBrothersHead = 0;
- }
- break;
- ******************/
-
- case FONT_USER_ITEM:
- GetMouse(&pt);
- r = GetDItemRect(gDialog,FONT_LABEL_ITEM);
- InvertRect(&r);
- part = TrackControl(gFontPopUp,pt,(Ptr)-1);
- InvertRect(&r);
-
- item = GetCtlValue(gFontPopUp);
- privateData = (MenuHandle)(*gFontPopUp)->contrlData;
- menuHandle = (popupPrivateDataHdl)(*privateData)->mHandle;
-
- GetItem(menuHandle, item, &fontName);
- GetFNum(fontName, &fontNum);
-
- if (fontNum != gFontNum) {
- gFontNum = fontNum;
- ZoomRect(&r,&gSampleRect,TRUE,FALSE);
- DrawSampleString();
- }
-
- break;
-
- case ALIGN_USER_ITEM:
- GetMouse(&pt);
- r = GetDItemRect(gDialog,ALIGN_LABEL_ITEM);
- InvertRect(&r);
- part = TrackControl(gAlignPopUp,pt,(Ptr)-1);
- InvertRect(&r);
-
- item = GetCtlValue(gAlignPopUp);
- if (item != gAlign) {
- gAlign = item;
- ZoomRect(&r,&gSampleRect,TRUE,FALSE);
- DrawSampleString();
- }
-
- break;
-
- case SIZE_USER_ITEM:
- GetMouse(&pt);
- r = GetDItemRect(gDialog,SIZE_LABEL_ITEM);
- InvertRect(&r);
- part = TrackControl(gSizePopUp,pt,(Ptr)-1);
- InvertRect(&r);
-
- item = GetCtlValue(gSizePopUp);
- privateData = (MenuHandle)(*gSizePopUp)->contrlData;
- menuHandle = (popupPrivateDataHdl)(*privateData)->mHandle;
-
- GetItem(menuHandle, item, &sizeStr);
- StringToNum(sizeStr,&sizeLong);
-
- if (sizeLong != (long)gSize) {
- gSize = sizeLong;
- ZoomRect(&r,&gSampleRect,TRUE,FALSE);
- DrawSampleString();
- }
- break;
-
- default:
- break;
- }
- }
-
- SetPort(savePort);
- }
-
- /* ----------------------------------------------
- Handle special dialog thangs.
- ---------------------------------------------- */
- pascal Boolean DialogFilter(DialogPtr d, EventRecord *e, short *item)
- {
- short type;
- Handle h;
- Rect r;
- short chr, mod, itemNum;
- long tick;
-
- if (e->what == updateEvt) {
- if (d == (DialogPtr)e->message) DrawSampleString();
- return(false);
- }
-
- if (e->what != keyDown) return(false);
-
- itemNum = 0;
-
- chr = e->message & charCodeMask;
- mod = e->modifiers & keyCodeMask;
-
- if ((chr == 0x0D) || (chr == 0x03)) { /* If return or enter... */
- if (!(mod & (cmdKey + optionKey + controlKey))) itemNum = 1;
- }
-
- if (itemNum) {
- GetDItem(d, itemNum, &type, &h, &r);
- HiliteControl((ControlHandle)h, 1);
- tick = TickCount();
- while (TickCount() < tick + 8);
- HiliteControl((ControlHandle)h, 0);
- *item = itemNum;
- return(true);
- }
-
- return(false);
- }
-
- /* ----------------------------------------------
- Create our dialog and our controls for the standard
- System 7.0 Pop-Up Menus.
-
- We also take a few moments to initialize some other
- variables here as well.
- ---------------------------------------------- */
- void CreateObjects(void)
- {
- Rect r;
-
- gDialog = GetNewDialog(DIALOG_ID,nil,(WindowPtr)-1L);
- if (!gDialog) ExitApplication(TRUE);
-
- r = GetDItemRect(gDialog, FONT_USER_ITEM);
- gFontPopUp = NewControl(gDialog,
- &r,
- (char*)'\p',
- TRUE,
- popupTitleLeftJust + popupTitleNoStyle,
- FONT_MENU_ID,
- 0, /* width of title? */
- popupMenuCDEFProc + popupUseAddResMenu + popupFixedWidth,
- 'FONT');
-
- if (!gFontPopUp) ExitApplication(TRUE);
-
- r = GetDItemRect(gDialog, ALIGN_USER_ITEM);
- gAlignPopUp = NewControl(gDialog,
- &r,
- (char*)'\p',
- TRUE,
- popupTitleLeftJust + popupTitleNoStyle,
- ALIGN_MENU_ID,
- 0, /* width of title? */
- popupMenuCDEFProc + popupFixedWidth,
- (long)nil);
-
- if (!gAlignPopUp) ExitApplication(TRUE);
-
- r = GetDItemRect(gDialog, SIZE_USER_ITEM);
- gSizePopUp = NewControl(gDialog,
- &r,
- (char*)'\p',
- TRUE,
- popupTitleLeftJust + popupTitleNoStyle,
- SIZE_MENU_ID,
- 0, /* width of title? */
- popupMenuCDEFProc + popupFixedWidth,
- (long)nil);
-
- if (!gSizePopUp) ExitApplication(TRUE);
-
- gFontLabelRect = GetDItemRect(gDialog, FONT_LABEL_ITEM);
- gAlignLabelRect = GetDItemRect(gDialog, ALIGN_LABEL_ITEM);
- gSizeLabelRect = GetDItemRect(gDialog, SIZE_LABEL_ITEM);
- gSampleRect = GetDItemRect(gDialog, SAMPLE_USER_ITEM);
-
- SetDItemProc(gDialog, SAMPLE_USER_ITEM, (ProcPtr)&DrawGrayFrameMinusText);
- SetDItemProc(gDialog, MENU_OUTLINE_USER_ITEM, (ProcPtr)&DrawGrayFrame);
-
- gSampleStr = GetString(SAMPLE_TEXT_STR);
- if (!gSampleStr) ExitApplication(TRUE);
- }
-
- /* ----------------------------------------------
- draw some text
- ---------------------------------------------- */
- void DrawSampleString()
- {
- Rect r;
- short just;
-
- TextFont(gFontNum); /* set the font */
- TextSize(gSize); /* and the size */
-
- switch (gAlign) { /* figure out how we are to align our text */
- case ALIGN_LEFT_ITEM:
- just = teJustLeft;
- break;
- case ALIGN_CENTER_ITEM:
- just = teJustCenter;
- break;
- case ALIGN_RIGHT_ITEM:
- just = teJustRight;
- break;
- }
-
- r = gSampleRect; /* copy the useritem rect since we have to change it */
- InsetRect(&r,7,7); /* inset it */
- EraseRect(&r); /* erase the area */
-
- HLock((Handle)gSampleStr);
- TextBox(*gSampleStr + sizeof(Byte), *gSampleStr[0] ,&r, just); /* draw the text! */
- HUnlock((Handle)gSampleStr);
-
- TextFont(systemFont); /* restore the font */
- TextSize(12);
- }
-
- /* ----------------------------------------------
- draw a gray framed item.
- ---------------------------------------------- */
- pascal void DrawGrayFrame( register DialogPtr d,
- register short item)
- {
- Rect r;
-
- r = GetDItemRect(d, item);
- PenNormal();
- PenPat(gray);
- FrameRect(&r);
- PenNormal();
- }
-
- /* ----------------------------------------------
- draw a gray framed item making ammends for a
- static text item which is one item less that
- the useritem to be framed.
- ---------------------------------------------- */
- pascal void DrawGrayFrameMinusText( register DialogPtr d,
- register short item)
- {
- Rect r, rT;
-
- rT = GetDItemRect(d, item-1); /* Text */
- r = GetDItemRect(d, item); /* User item */
- PenNormal();
- PenPat(gray);
- MoveTo(rT.right + 2, r.top);
- LineTo(r.right, r.top);
- LineTo(r.right, r.bottom);
- LineTo(r.left, r.bottom);
- LineTo(r.left, r.top);
- LineTo(rT.left - 3, r.top);
- PenNormal();
- }
-
- /* ----------------------------------------------
- Return the rectangle of a dialog item
- ---------------------------------------------- */
- Rect GetDItemRect(DialogPtr d, short item)
- {
- short kind;
- Handle h;
- Rect r;
-
- GetDItem (d, item, &kind, &h, &r);
- return (r);
- }
-
- /* ----------------------------------------------
- Set the update proc of a user item
- ---------------------------------------------- */
- void SetDItemProc(DialogPtr d, short item, ProcPtr proc)
- {
- short type;
- Handle h;
- Rect r;
-
- GetDItem (d, item, &type, &h, &r);
- SetDItem(d, item, type, proc, &r);
- }
-
-
- /* ----------------------------------------------
- Make sure we can run in this environment. Gestalt
- checks may also be nice to have here but until THINK
- C 5.0 comes out, forget it!
- ---------------------------------------------- */
- void CheckEnvironment(void)
- {
- SysEnvRec e;
- OSErr err;
-
- if (!(err = SysEnvirons (curSysEnvVers, &e))) {
- if (e.systemVersion < 0x0700)
- ExitApplication(TRUE);
- } else {
- ExitApplication(TRUE);
- }
- }
-
- /* ----------------------------------------------
- play an ‘snd ’ resource
- ---------------------------------------------- */
- void PlaySound(short id)
- {
- Handle h;
- OSErr err;
-
- h = GetResource('snd ', id);
- if (h != nil) {
- LoadResource(h);
- HNoPurge(h);
- err = SndPlay(nil, h, FALSE);
- HPurge(h);
- ReleaseResource(h);
- }
- }
-
- /* ----------------------------------------------
- utility routine used by ZoomRect()
- ---------------------------------------------- */
- short Blend(register Fixed fract,
- short smallCoord,
- short bigCoord)
- {
- return (FixRound(FixMul(fract, (long) bigCoord << 16) +
- FixMul(0x00010000 - fract, (long) smallCoord << 16)));
- }
-
- /* ----------------------------------------------
- draw some zoooooooom rects!
- ---------------------------------------------- */
- #define ZOOM_STEPS 16
- #define DELAY_TICKS 1
-
- void ZoomRect(register Rect *smallRect,
- register Rect *bigRect,
- Boolean zoomUp,
- Boolean useWMgrPort)
- {
- register Fixed fract, factor;
- GrafPtr savePort;
- GrafPtr wMgrPort;
- PenState savePenState;
- Rect r1, r2, r3, r4;
- register short i, j;
- long ticks;
-
- if (useWMgrPort) {
- GetPort(&savePort);
- GetWMgrPort(&wMgrPort);
- SetPort(wMgrPort);
- }
-
- GetPenState(&savePenState);
- PenPat(gray);
- PenMode(notPatXor);
-
- if (zoomUp) {
- r1 = *smallRect;
- factor = FixRatio(6, 5);
- fract = FixRatio(541, 10000); /* 5/6 ^ 16 */
- } else {
- r1 = *bigRect;
- factor = FixRatio(5, 6);
- fract = 0x00010000;
- }
-
- r3 = r2 = r1;
- FrameRect(&r1);
-
- for (i = 0; i < ZOOM_STEPS; ++i) {
- r4.top = Blend(fract, smallRect->top, bigRect->top);
- r4.left = Blend(fract, smallRect->left, bigRect->left);
- r4.bottom = Blend(fract, smallRect->bottom, bigRect->bottom);
- r4.right = Blend(fract, smallRect->right, bigRect->right);
- FrameRect(&r4);
- FrameRect(&r1);
- r1 = r2;
- r2 = r3;
- r3 = r4;
-
- fract = FixMul(fract, factor);
-
- Delay(DELAY_TICKS,&ticks);
- }
-
- FrameRect(&r1);
- FrameRect(&r2);
- FrameRect(&r3);
- if (useWMgrPort) {
- SetPort(savePort);
- }
- SetPenState(&savePenState);
- }
-
- /* ----------------------------------------------
- Beep and exit!
- ---------------------------------------------- */
- void ExitApplication(Boolean error)
- {
- if (gFontPopUp) DisposeControl(gFontPopUp); /* clean up handles */
- if (gAlignPopUp) DisposeControl(gAlignPopUp);
- if (gSizePopUp) DisposeControl(gSizePopUp);
- if (gDialog) DisposDialog(gDialog);
- if (gSampleStr) ReleaseResource(gSampleStr);
-
- if (error)
- Alert(GENERIC_ALRT_ID,nil);
-
- ExitToShell();
- }
-
- /* ----------------------------------------------
- Initialize the Toolbox
- ---------------------------------------------- */
- void InitToolBox(void)
- {
-
- InitGraf(&thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
- }